﻿// -----------------------------------------------------------------------
// <copyright file="AlienShip1.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace SpaceshipDuel
{
    /// <summary>
    /// Alienraumschiff Klasse 3
    /// </summary>
    public class AlienShip3 : AlienShip
    {
        #region Private fields

        Vector2 nearestObstacle;
        Vector2 player1;
        Vector2 player2;
        float maxSpeed = 4.0f;
        const double PLAYERDISTANCE = 2000;
        bool evadePlayer;

        #endregion Private fields

        #region Construction

        public AlienShip3(TextureData newShipTextureData, TextureData newShotTextureData, Vector2 newCenter, int newWorldSize, ref List<Bullet> newBullets)
        {
            textureData = newShipTextureData;
            shotTextureData = newShotTextureData;
            center = newCenter;
            rotationAngle = 0f;
            worldSize = newWorldSize;
            velocity = new Vector2(0, 0);  // Richtungsvektor der aktuellen Ausrichtung setzen
            bullets = newBullets;

            bulletSpeed = 1.8f;
            maxBulletDistance = 2000;
            shieldPower = 60;
            maxShieldPower = 100;
            rotation = 0.020f;          // Rotationsgeschwindigkeit
            speed = maxSpeed;           // Fluggeschwindigkeit
            nextBulletInterval = 0.6f;
            nextBulletTimer = new WaitTimer(nextBulletInterval);

            nearestObstacle = new Vector2(-1000, -1000);
            player1 = new Vector2(-1000, -1000);
            player2 = new Vector2(-1000, -1000);
            evadePlayer = false;
        }

        #endregion Construction

        #region Public properties

        public Vector2 NearestObstacle
        {
            set { nearestObstacle = value; }
        }

        public Vector2 Player1
        {
            set { player1 = value; }
        }

        public Vector2 Player2
        {
            set { player2 = value; }
        }

        #endregion Public properties

        #region Public methods

        /// <summary>
        /// Update-Methode
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            velocity.X = (float)(Math.Sin(rotationAngle) * speed);
            velocity.Y = (float)(-Math.Cos(rotationAngle) * speed);
            center += velocity;
            rotationAngle += rotation;
            rotationAngle = (float)(rotationAngle % (Math.PI * 2));

            // Steuerunglogik unter Einbezug von Objektpositionen
            Evasion(gameTime);

            base.CheckPosition();
        }


        #endregion Public methods

        #region Private methods

        /// <summary>
        /// Schießen
        /// </summary>
        /// <param name="gameTime"></param>
        private void Shoot(GameTime gameTime)
        {
            if (nextBulletTimer.IsElapsed(gameTime.ElapsedGameTime.TotalSeconds) == true)
            {
                Vector2 bulletDirection = new Vector2((float)Math.Sin(rotationAngle), (float)-Math.Cos(rotationAngle));
                bulletDirection.Normalize();
                Vector2 tangente = new Vector2(-bulletDirection.Y, bulletDirection.X);
                Vector2 bulletPosition = center + bulletDirection * 32;
                Bullet bullet1 = new Bullet(shotTextureData, bulletPosition + tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);
                Bullet bullet2 = new Bullet(shotTextureData, bulletPosition - tangente * 5, this.worldSize, this.speed + bulletSpeed, this.rotationAngle, bulletDirection, maxBulletDistance);

                bullets.Add(bullet1);
                bullets.Add(bullet2);
                nextBulletTimer.Reset();
                //SoundProvider.SfxLaserEnemy.Play();
            }
        }

        private void Evasion(GameTime gameTime)
        {
            double distance = CollisionHelper.GetDistance(center, nearestObstacle, worldSize);
            double player1Distance = CollisionHelper.GetDistance(center, player1, worldSize);
            double player2Distance = CollisionHelper.GetDistance(center, player2, worldSize);

            if (distance < 800 && player1Distance > PLAYERDISTANCE && player2Distance > PLAYERDISTANCE)
            {
                evadePlayer = false;
                EvadeObstacle(distance);
            }
            else if (player1Distance <= PLAYERDISTANCE && player1Distance < player2Distance)
            {
                speed = maxSpeed;
                TargetPlayer(gameTime, player1Distance, player1);
            }
            else if (player2Distance <= PLAYERDISTANCE)
            {
                speed = maxSpeed;
                TargetPlayer(gameTime, player2Distance, player2);
            }
            else
            {
                speed = maxSpeed;
                rotation = 0.0f;
                evadePlayer = false;
            }
        }

        private void EvadeObstacle(double distance)
        {
            double diffAngle = CalculateDiffAngle(nearestObstacle, center);

            // Winkelunterschied kleiner gleich 20°
            if (Math.Abs(diffAngle) <= Math.PI / 3)
            {
                if (diffAngle < 0)
                {
                    if (distance < 100)
                    {
                        rotation = (float)(Math.PI / F1);
                        speed = maxSpeed / V1;
                    }
                    else if (distance < 200)
                    {
                        rotation = (float)(Math.PI / F2);
                        speed = maxSpeed / V2;
                    }
                    else if (distance < 300)
                    {
                        rotation = (float)(Math.PI / F3);
                        speed = maxSpeed / V3;
                    }
                    else if (distance < 400)
                    {
                        rotation = (float)(Math.PI / F4);
                        speed = maxSpeed / V4;
                    }
                    else if (distance < 800)
                    {
                        rotation = (float)(Math.PI / F5);
                        speed = maxSpeed / V5;
                    }
                }
                else
                {
                    if (distance < 100)
                    {
                        rotation = (float)(-Math.PI / F1);
                        speed = maxSpeed / V1;
                    }
                    else if (distance < 200)
                    {
                        rotation = (float)(-Math.PI / F2);
                        speed = maxSpeed / V2;
                    }
                    else if (distance < 300)
                    {
                        rotation = (float)(-Math.PI / F3);
                        speed = maxSpeed / V3;
                    }
                    else if (distance < 400)
                    {
                        rotation = (float)(-Math.PI / F4);
                        speed = maxSpeed / V4;
                    }
                    else if (distance < 800)
                    {
                        rotation = (float)(-Math.PI / F5);
                        speed = maxSpeed / V5;
                    }
                }
            }
            else
                rotation = 0.0f;
        }

        // Spieler angreifen
        private void TargetPlayer(GameTime gameTime, double distance, Vector2 playerPos)
        {
            double diffAngle = CalculateDiffAngle(playerPos, center);

            if (Math.Abs(diffAngle) <= Math.PI / 3)
            {
                if (diffAngle < 0)
                {
                    // Ausweichen
                    if (evadePlayer == true)
                    {
                        if (distance < 100)
                        {
                            rotation = (float)(Math.PI / F1);
                            speed = maxSpeed / V1;
                        }
                        else if (distance < 150)
                        {
                            rotation = (float)(Math.PI / F2);
                            speed = maxSpeed / V2;
                        }
                        else if (distance < 300)
                        {
                            rotation = (float)(Math.PI / F3);
                            speed = maxSpeed / V3;
                        }
                        else
                        {
                            rotation = 0.0f;
                            speed = maxSpeed;
                            if (distance > 900)
                                evadePlayer = false;
                        }
                    }

                    // Angriff
                    else
                    {
                        if (distance < 300)
                        {
                            rotation = (float)(-Math.PI / F0);
                            evadePlayer = true;
                        }
                        else if (distance < 500)
                            rotation = (float)(-Math.PI / F1);
                        else if (distance < 700)
                            rotation = (float)(-Math.PI / F2);
                        else if (distance < 900)
                            rotation = (float)(-Math.PI / F3);
                        else if (distance < 1100)
                            rotation = (float)(-Math.PI / F4);
                    }
                }
                else
                {
                    // Ausweichen
                    if (evadePlayer == true)
                    {
                        if (distance < 100)
                        {
                            rotation = (float)(-Math.PI / F1);
                            speed = maxSpeed / V1;
                        }
                        else if (distance < 150)
                        {
                            rotation = (float)(-Math.PI / F2);
                            speed = maxSpeed / V2;
                        }
                        else if (distance < 200)
                        {
                            rotation = (float)(-Math.PI / F3);
                            speed = maxSpeed / V3;
                        }
                        else
                        {
                            rotation = 0.0f;
                            speed = maxSpeed;
                            if (distance > 900)
                                evadePlayer = false;
                        }
                    }

                    // Angriff
                    else
                    {
                        if (distance < 300)
                        {
                            rotation = (float)(Math.PI / F0);
                            evadePlayer = true;
                        }
                        else if (distance < 500)
                            rotation = (float)(Math.PI / F1);
                        else if (distance < 700)
                            rotation = (float)(Math.PI / F2);
                        else if (distance < 900)
                            rotation = (float)(Math.PI / F3);
                        else if (distance < 1100)
                            rotation = (float)(Math.PI / F4);
                    }
                }
            }
            else
                if (distance < 600)
                    rotation = 0.0f;
                else
                    rotation = -0.01f;

            if (Math.Abs(diffAngle) <= Math.PI / 3 && evadePlayer == false)
                Shoot(gameTime);
        }

        // Winkeldifferenz zwischen Alienschiff und Ziel berechnen
        // wird zum Ausweichen und Angreifen benötigt
        private double CalculateDiffAngle(Vector2 target, Vector2 center)
        {
            // Erzeuge virtuelle Koordinaten zur Zielerfassung
            Vector2 newTarget = target;
            Vector2 newCenter = center;

            float resultX = (float)Math.Abs(target.X - center.X);
            if (resultX > worldSize / 2)
            {
                newTarget.X = (target.X + worldSize / 2) % worldSize;
                newCenter.X = (center.X + worldSize / 2) % worldSize;
            }

            float resultY = (float)Math.Abs(target.Y - center.Y);
            if (resultY > worldSize / 2)
            {
                newTarget.Y = (target.Y + worldSize / 2) % worldSize;
                newCenter.Y = (center.Y + worldSize / 2) % worldSize;
            }

            double rotAngle = (Math.Atan2(newTarget.Y - newCenter.Y, newTarget.X - newCenter.X) + Math.PI / 2);

            return (rotAngle - rotationAngle);
        }

        #endregion Private methods
    }
}
